window.onload = function () {
  const fInput = document.querySelector('#file')
  const preViewImg = document.querySelector('#preview')
  const ot = document.querySelector('#output')
  const workspace = document.querySelector('#workspace')

  const cropBox = document.querySelector('#crop-box')
  const cropResultContainer = document.querySelector('#cropped-result')
  let cvs

  let crop = {
    x: 0,
    y: 0,
    width: 150,
    height: 150,
  }

  fInput.addEventListener('change', e => {
    const file = e.target.files[0]
    if (!file) return

    // 获取文件
    const imageUrl = window.URL.createObjectURL(file)
    preViewImg.src = imageUrl

    preViewImg.onload = () => {
      workspace.classList.remove('hidden')
      crop.x = preViewImg.offsetLeft + 10
      crop.y = preViewImg.offsetTop + 10
      crop.width = 150
      crop.height = 150

      updateCropBoxStyle()
      updateCanvasPreview()
    }
  })

  function updateCropBoxStyle() {
    cropBox.style.left = crop.x + 'px'
    cropBox.style.top = crop.y + 'px'
    cropBox.style.width = crop.width + 'px'
    cropBox.style.height = crop.height + 'px'
  }

  // 图片裁剪,这里呢有一个方便的方案将数据裁剪到canvas上获取Blob在看情况转换需要的类型
  function updateCanvasPreview() {
    if (!preViewImg.complete || preViewImg.naturalWidth === 0) {
      return
    }

    if (!cvs) {
      cvs = document.createElement('canvas')
      cropResultContainer.innerHTML = ''
      cropResultContainer.appendChild(cvs)
    }

    const scaleX = preViewImg.naturalWidth / preViewImg.clientWidth
    const scaleY = preViewImg.naturalHeight / preViewImg.clientHeight

    const imgOffsetX = preViewImg.offsetLeft
    const imgOffsetY = preViewImg.offsetTop

    const relativeCropX = crop.x - imgOffsetX
    const relativeCropY = crop.y - imgOffsetY

    const sourceX = relativeCropX * scaleX
    const sourceY = relativeCropY * scaleY
    const sourceWidth = crop.width * scaleX
    const sourceHeight = crop.height * scaleY

    if (sourceWidth <= 0 || sourceHeight <= 0) return

    cvs.width = sourceWidth
    cvs.height = sourceHeight

    const ctx = cvs.getContext('2d')
    ctx.drawImage(
      preViewImg,
      sourceX,
      sourceY,
      sourceWidth,
      sourceHeight,
      0,
      0,
      sourceWidth,
      sourceHeight
    )
  }

  let activeHandle = null
  let startX, startY, startCropX, startCropY, startCropWidth, startCropHeight

  cropBox.addEventListener('mousedown', e => {
    e.preventDefault()

    startX = e.clientX
    startY = e.clientY
    startCropX = crop.x
    startCropY = crop.y
    startCropWidth = crop.width
    startCropHeight = crop.height

    if (e.target.classList.contains('handle')) {
      activeHandle = e.target
    } else {
      activeHandle = 'box'
    }

    document.addEventListener('mousemove', handleMouseMove)
    document.addEventListener('mouseup', handleMouseUp)
  })

  function handleMouseMove(e) {
    if (!activeHandle) return

    const dx = e.clientX - startX
    const dy = e.clientY - startY

    const imgRect = preViewImg.getBoundingClientRect()

    const imgOffsetX = preViewImg.offsetLeft
    const imgOffsetY = preViewImg.offsetTop

    if (activeHandle === 'box') {
      crop.x = startCropX + dx
      crop.y = startCropY + dy
    } else {
      if (activeHandle.classList.contains('top-left')) {
        crop.x = startCropX + dx
        crop.y = startCropY + dy
        crop.width = startCropWidth - dx
        crop.height = startCropHeight - dy
      } else if (activeHandle.classList.contains('top-right')) {
        crop.y = startCropY + dy
        crop.width = startCropWidth + dx
        crop.height = startCropHeight - dy
      } else if (activeHandle.classList.contains('bottom-left')) {
        crop.x = startCropX + dx
        crop.width = startCropWidth - dx
        crop.height = startCropHeight + dy
      } else if (activeHandle.classList.contains('bottom-right')) {
        crop.width = startCropWidth + dx
        crop.height = startCropHeight + dy
      }
    }

    crop.x = Math.max(imgOffsetX, crop.x)
    crop.y = Math.max(imgOffsetY, crop.y)
    crop.width = Math.max(20, crop.width)
    crop.height = Math.max(20, crop.height)

    if (crop.x + crop.width > imgOffsetX + imgRect.width) {
      crop.width = imgOffsetX + imgRect.width - crop.x
    }
    if (crop.y + crop.height > imgOffsetY + imgRect.height) {
      crop.height = imgOffsetY + imgRect.height - crop.y
    }

    updateCropBoxStyle()
    updateCanvasPreview()
  }

  function handleMouseUp() {
    activeHandle = null
    document.removeEventListener('mousemove', handleMouseMove)
    document.removeEventListener('mouseup', handleMouseUp)
  }

  ot.onclick = function () {
    if (!cvs || cvs.width === 0 || cvs.height === 0) {
      alert('请先选择图片并进行裁剪！')
      return
    }
    cvs.toBlob(blob => {
      const url = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = '裁剪图片.png'
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      window.URL.revokeObjectURL(url)
    }, 'image/png')
  }
}
